// core
package lib

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"log"
	"math"
	"sync"
	"time"

	"github.com/garyburd/redigo/redis"
)

// Prepare ,stmt
type Core struct {
	DB        *sql.DB
	RedisPool *redis.Pool
	Count     int
	Limit     int
	Success   int
	CreateWg  sync.WaitGroup
}

type TableData struct {
	SimID                int
	SIM                  string
	SimState             int
	ICCID                string
	PackageID            int
	PackageName          string
	UsageToPeriod        float64
	PeriodType           string
	PackageInfo          string
	ContractType         string
	IsUsageReset         bool
	HoldID               int
	PackagePeriod        int
	SurplusPeriod        int
	AmountUsageData      float64
	MonthUsageData       float64
	DataFlow             float64
	TotalMonthUsageFlow  float64
	FlowLeftTime         string
	ActiveTime           string
	VExpireTime          string
	OverUsageStopService bool
	HadAddPackage        bool
	RowNumber            int
}

//查询数据总条数
func (c *Core) Run() {
	c.Count = c.total()
	if c.Count == 0 {
		fmt.Println("没有要写入redis的数据")
		return
	}
	k := int(math.Ceil(float64(c.Count) / float64(c.Limit)))
	var wg sync.WaitGroup
	for i := 0; i < k; i++ {
		wg.Add(1)
		go func(j int) {
			defer wg.Done()
			startTime := time.Now().Unix()
			rows := c.lists(j * c.Limit)
			endTime := time.Now().Unix()
			fmt.Printf("第 %d 次查询总共执行了 %d 秒\n", j, endTime-startTime)

			if len(rows) > 0 {
				c.writeCache(rows)
			}
			endTime = time.Now().Unix()
			fmt.Printf("第 %d 次成功写入缓存 %d 条，总共执行了 %d 秒\n", j, len(rows), endTime-startTime)
			return
		}(i)
	}
	wg.Wait()
	return
}

//随机生成数据

func (c *Core) RunCreateData(k, num int) {
	startTime := time.Now().Unix()
	for i := 0; i < k; i++ {
		c.CreateWg.Add(1)
		go c.CreateData(num)
	}
	c.CreateWg.Wait()
	endTime := time.Now().Unix()

	fmt.Printf("%d次插入数据 %d 条，总共使用了%d秒\n", k, num, endTime-startTime)
	return
}

//随机生成数据

func (c *Core) CreateData(k int) {
	defer c.CreateWg.Done()
	db, _ := c.DB.Begin()
	defer db.Commit()
	insertPrepare, err := db.Prepare("INSERT INTO t set created = ?")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer insertPrepare.Close()
	t := time.Now().Unix()
	for i := 0; i < k; i++ {
		insertPrepare.Exec(t)
	}
	return
}

//查询数据总条数
func (c *Core) total() (num int) {
	sql := "SELECT COUNT(*) as size "
	sql += "FROM std_SIMInfo s WITH(NOLOCK) "
	sql += "left join D_SIMPackageType p WITH(NOLOCK) on s.PackageID=p.RecID "
	sql += "WHERE "
	sql += "s.isDeleted=0 "
	sql += "and s.SimFromType=1 "
	sql += "and s.SimState in (3,4) "
	sql += "and s.LastActiveTime is not null "
	sql += "and s.VExpireTime is not null"
	fmt.Println("查询总数sql语句：", sql)
	// "select count(*) from t limit 1"
	err := c.DB.QueryRow(sql).Scan(&num)
	if err != nil {
		fmt.Println("select total faild,error messge:", err)
	}
	return
}

//分页查询
func (c *Core) lists(start int) []TableData {
	sql := "select * from ("
	sql += "SELECT "
	sql += "s.RecID SimID,"
	sql += "s.SIM,"
	sql += "s.SimState,"
	sql += "s.GUID as ICCID,"
	sql += "isnull(s.PackageID, 0) PackageID,"
	sql += "isnull(p.PackageName, '') PackageName,"
	sql += "isnull(p.UsageToPeriod,0)/1024 UsageToPeriod,"
	sql += "isnull(p.PeriodType, '') PeriodType,"
	sql += "isnull(p.PackageInfo, '') PackageInfo,"
	sql += "isnull(p.ContractType, '') ContractType,"
	sql += "isnull(p.isUsageReset, 0) isUsageReset,"
	sql += "isnull(s.HoldID, 0) HoldID,"
	sql += "isnull(s.PackagePeriod, 0) PackagePeriod,"
	sql += "isnull(s.SurplusPeriod,isnull(p.PeriodDays,0)) SurplusPeriod,"
	sql += "isnull(s.AmountUsageData,0)/1024 AmountUsageData,"
	sql += "isnull(s.MonthUsageData,0)/1024 MonthUsageData,"
	sql += "isnull(s.UsageDataFlow,0)/1024 DataFlow,"
	sql += "isnull(s.TotalMonthUsageFlow,0)/1024 TotalMonthUsageFlow,"
	sql += "isnull(CONVERT(varchar(20),s.FlowLeftTime,120), '') FlowLeftTime,"
	sql += "isnull(CONVERT(varchar(10),s.LastActiveTime,120), '') ActiveTime,"
	sql += "isnull(CONVERT(varchar(10),s.VExpireTime,120), '') VExpireTime,"
	sql += "isnull(s.OverUsageStopService, 0) OverUsageStopService,"
	sql += "isnull(s.HadAddPackage,0) HadAddPackage,"
	sql += "ROW_NUMBER() OVER (ORDER BY s.SIM) AS RowNumber "
	sql += "FROM std_SIMInfo s WITH(NOLOCK) "
	sql += "LEFT JOIN D_SIMPackageType p WITH(NOLOCK) on s.PackageID=p.RecID "
	sql += "WHERE "
	sql += "s.isDeleted=0 "
	sql += "and s.SimFromType=1 "
	sql += "and s.SimState in (3,4) "
	sql += "and s.LastActiveTime is not null "
	sql += "and s.VExpireTime is not null "
	sql += ") a "
	sql += "where RowNumber >= ? and RowNumber < ?"
	fmt.Println("分页查询sql语句：", sql, start, start+c.Limit)
	//"select id,created from t limit ?,?"
	rows, err := c.DB.Query(sql, start, start+c.Limit)
	results := make([]TableData, 0)
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	var data TableData
	for rows.Next() {
		err := rows.Scan(
			&data.SimID,
			&data.SIM,
			&data.SimState,
			&data.ICCID,
			&data.PackageID,
			&data.PackageName,
			&data.UsageToPeriod,
			&data.PeriodType,
			&data.PackageInfo,
			&data.ContractType,
			&data.IsUsageReset,
			&data.HoldID,
			&data.PackagePeriod,
			&data.SurplusPeriod,
			&data.AmountUsageData,
			&data.MonthUsageData,
			&data.DataFlow,
			&data.TotalMonthUsageFlow,
			&data.FlowLeftTime,
			&data.ActiveTime,
			&data.VExpireTime,
			&data.OverUsageStopService,
			&data.HadAddPackage,
			&data.RowNumber)
		if err != nil {
			log.Fatal(err)
		}
		results = append(results, data)
		//results[data.Geui] = data
	}
	if err := rows.Err(); err != nil {
		log.Fatal(err)
	}
	return results
}

// 写入缓存

func (c *Core) writeCache(rows []TableData) {
	r1, r2 := c.RedisPool.Get(), c.RedisPool.Get()
	r1.Do("SELECT", 0)
	r2.Do("SELECT", 1)
	defer r1.Close()
	defer r2.Close()
	for _, v := range rows {
		jv, _ := json.Marshal(v)
		r1.Send("SET", v.SimID, jv)
		r2.Send("SET", v.ICCID, v.SimID)
	}
	r1.Flush()
	r2.Flush()
	return
	/*
		r, err := redis.Do("MSET", rows)
		if err != nil && r == 1 {
			return 1
		} else {
			return 0
		}
	*/
}
